/*
  -------------------------------------------------------------------------
              JavaScript Form Validator (gen_validatorv31.js)
              Version 3.1.1
    Copyright (C) 2003-2008 JavaScript-Coder.com. All rights reserved.
    You can freely use this script in your Web pages.
    You may adapt this script for your own needs, provided these opening credit
    lines are kept intact.
        
    The Form validation script is distributed free from JavaScript-Coder.com
    For updates, please visit:
    http://www.javascript-coder.com/html-form/javascript-form-validation.phtml
    
    Questions & comments please send to form.val at javascript-coder.com
  -------------------------------------------------------------------------  
*/
var Validator=new Class();
Validator._Validator=new Class({  
    initialize : function(className, error, test, options) {
        if(typeof test == 'function'){
            this.options =new Hash(options);
            this._test = test;
        } else {
            this.options =new Hash(test);
            this._test = function(){return true};
        }
        this.error = error || 'Validation failed.';
        this.className = className;
    },
    test : function(v, elm) {
        var result=this._test(v,elm);
        this.options.each(function(key, value, hash){
            result &=this.methods[key]?this.methods[key](v,elm,value):true;
            //Validator.methods[p.key] ? Validator.methods[p.key](v,elm,p.value) : true; 
        });
        return result;
    },
    methods : {
        pattern : function(v,elm,opt) {return Validation.get('IsEmpty').test(v) || opt.test(v)},
        minLength : function(v,elm,opt) {return v.length >= opt},
        maxLength : function(v,elm,opt) {return v.length <= opt},
        min : function(v,elm,opt) {return v >= parseFloat(opt)}, 
        max : function(v,elm,opt) {return v <= parseFloat(opt)},
        notOneOf : function(v,elm,opt) {return $A(opt).all(function(value) {
            return v != value;
        })},
        oneOf : function(v,elm,opt) {return $A(opt).any(function(value) {
            return v == value;
        })},
        is : function(v,elm,opt) {return v == opt},
        isNot : function(v,elm,opt) {return v != opt},
        equalToField : function(v,elm,opt) {return v == $F(opt)},
        notEqualToField : function(v,elm,opt) {return v != $F(opt)},
        include : function(v,elm,opt) {return $A(opt).all(function(value) {
            return Validation.get(value).test(v,elm);
        })}
            
    }
});

Validator.methods = {
    '_LikeNoIDIEverSaw_' : new Validator._Validator('_LikeNoIDIEverSaw_','',{})
}; 
Validator.add = function(classname, error, test, options) {
    var nv = {};
    nv[classname] = new Validator._Validator(classname, error, test, options);
    $extend(Validator.methods, nv);
};
Validator.addAllThese = function(validators) {
    var nv = {};
    validators.each(function(value) {
            nv[value[0]] = new Validator._Validator(value[0], value[1], value[2], (value.length > 3 ? value[3] : {}));
        });
    $extend(Validator.methods, nv);
};
Validator.get = function(name) {
    return  Validator.methods[name] ? Validator.methods[name] : Validator.methods['_LikeNoIDIEverSaw_'];
};
$extend(Validator,new Class({
    initialize : function(form_id, options){
        this.validate_tag='select, input';
        this.form=$(form_id);
        this.options=$merge({
            onSubmit : true,
            stopOnFirst : false,
            immediate : false,
            focusOnError : true,
            useTitles : false,
            onFormValidate : function(result, form) {},
            onElementValidate : function(result, elm) {}
            }, options);
        if(this.options.onSubmit){
            this.form.addEvent('submit', this.onSubmit.bind(this));
        }
        
        if(this.options.immediate){
            var useTitles = this.options.useTitles;
            var callback = this.options.onElementValidate;
            $each(this.form.getElements(this.validate_tag), function(elem){
                elem.addEvent('blur', function(event){
                    this.validate_element(event.target,{useTitle : useTitles, onElementValidate : callback});
                    //Validation.validate(Event.element(ev),{useTitle : useTitles, onElementValidate : callback});
                }.bind(this));
            }.bind(this));
        }   
    },
    onSubmit : function(event){
        if(!this.validate_form()){
            event.stop();  
        }   
    },
    

    validate_form : function() {
        var result = true;
        var useTitles = this.options.useTitles;
        var callback = this.options.onElementValidate;
        if(this.options.stopOnFirst) {
            var elements=this.form.getElements(this.validate_tag);
            for(var i=0;i<elements.length;i++){
                if(!this.validate_element(elements[i],{useTitle : useTitles, onElementValidate : callback})){
                    result=false; 
                    break;
                }
            }
        } else {
            $each(this.form.getElements(this.validate_tag), function(elm){
                if(!this.validate_element(elm,{useTitle : useTitles, onElementValidate : callback})){
                    result=false;
                }
            }.bind(this)); 
        }
        if(!result && this.options.focusOnError) {
            this.form.getElement('.validation-failed').focus();
            //Form.getElements(this.form).findAll(function(elm){return $(elm).hasClassName('validation-failed')}).first().focus()
        }
        this.options.onFormValidate(result, this.form);
        return result;
    },
    reset : function() {
        //Form.getElements(this.form).each(Validation.reset);
        $each(this.form.getElements(this.validate_tag), function(elem){
            this.reset_element(elem);
        }.bind(this));
    },                                   
    
    validate_element : function(elm, options){
        options = $merge({
            useTitle : false,
            onElementValidate : function(result, elm) {}
        }, options);
        var cn=elm.get('class');
        var result=true;
        $each(cn.split(' '), function(value){
            var test=this.test_element(value, elm, options.useTitle);
            options.onElementValidate(test, elm);
            if(!test){
                result=false;
            }
        }.bind(this));
        return result;

    },
    test_element : function(name, elm, useTitle) {
        var v = Validator.get(name);

        var prop = '__advice'+name.camelCase();
        try {  
                                
        if(this.isVisible(elm) && !v.test(elm.get('value'), elm)) {
            if(!elm[prop]) {
                 
                var advice = this.getAdvice(name, elm);
                if(advice == null) {
                    var errorMsg = useTitle ? ((elm && elm.get('title')) ? elm.get('title') : v.error) : v.error;
                    
                     advice= new Element('div', {
                        id: 'advice-'+name+'-'+this.getElmID(elm), 
                        class: 'validation-advice',
                        style: 'display:none',
                        text: errorMsg
                        });                     
                     
                    //$('error_message').set('text',advice.get('id'));  
                    switch (elm.get('type').toLowerCase()) {
                        case 'checkbox':
                        case 'radio':
                            var p = $(elm.parentNode);
                            if(p) {
                                advice.inject(p,'bottom');
                                //new Insertion.Bottom(p, advice);
                            } else {
                                advicelm.inject(elm,'after');
                                //new Insertion.After(elm, advice);
                            }
                            break;
                        default:
                            advice.inject(elm,'after');
                            //new Insertion.After(elm, advice);
                    }
                    test=elm;
                    test1=advice;
                    advice = this.getAdvice(name, elm);
                }

                if(typeof Effect == 'undefined') {
                    advice.set({'styles':{'display':'block'}});
                } else {
                    new Effect.Appear(advice, {duration : 1 });
                }
            }
            elm[prop] = true;
            elm.removeClass('validation-passed');
            elm.addClass('validation-failed');
            return false;
        } else {
            var advice = this.getAdvice(name, elm);
            if(advice != null) 
                 advice.set({'styles':{'display':'none'}});      
            elm[prop] = '';
            elm.removeClass('validation-failed');
            elm.addClass('validation-passed');
            return true;
        }
        } catch(e) {
            throw(e)
        }
    },
    isVisible : function(elm) { 
        while(elm.get('tag').toUpperCase() != 'BODY' && elm.get('tag').toUpperCase != 'HTML') {
            if(elm.get('display')=='none')
                return false;
            elm = $(elm.parentNode);
        }
        return true;
    },
    getAdvice : function(name, elm) {
        return $('advice-' + name + '-' + this.getElmID(elm)) || $('advice-' + this.getElmID(elm));
    },
    getElmID : function(elm) {
        return elm.get('id')? elm.get('id') : elm.get('name');
    },
    reset_element : function(elm) {
        elm = $(elm);
        var cn = elm.classNames();
        cn.each(function(value) {
            var prop = '__advice'+value.camelize();
            if(elm[prop]) {
                var advice = Validation.getAdvice(value, elm);
                advice.hide();
                elm[prop] = '';
            }
            elm.removeClassName('validation-failed');
            elm.removeClassName('validation-passed');
        });
    },
}));

Validator.add('IsEmpty', '', function(v) {
    return  ((v == null) || (v.length == 0)); // || /^\s+$/.test(v));
});

Validator.addAllThese([
    ['required', 'This is a required field.', function(v) {
                return !Validator.get('IsEmpty').test(v);
            }],
    ['validate-number', 'Please enter a valid number in this field.', function(v) {
                return Validator.get('IsEmpty').test(v) || (!isNaN(v) && !/^\s+$/.test(v));
            }],
    ['validate-digits', 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.', function(v) {
                return Validator.get('IsEmpty').test(v) ||  !/[^\d]/.test(v);
            }],
    ['validate-alpha', 'Please use letters only (a-z) in this field.', function (v) {
                return Validator.get('IsEmpty').test(v) ||  /^[a-zA-Z]+$/.test(v)
            }],
    ['validate-alphanum', 'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.', function(v) {
                return Validator.get('IsEmpty').test(v) ||  !/\W/.test(v)
            }],
    ['validate-date', 'Please enter a valid date.', function(v) {
                var test = new Date(v);
                return Validator.get('IsEmpty').test(v) || !isNaN(test);
            }],
    ['validate-email', 'Please enter a valid email address. For example fred@domain.com .', function (v) {
                return Validator.get('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
            }],
    ['validate-url', 'Please enter a valid URL.', function (v) {
                return Validator.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(v)
            }],
    ['validate-date-au', 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.', function(v) {
                if(Validator.get('IsEmpty').test(v)) return true;
                var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
                if(!regex.test(v)) return false;
                var d = new Date(v.replace(regex, '$2/$1/$3'));
                return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) && 
                            (parseInt(RegExp.$1, 10) == d.getDate()) && 
                            (parseInt(RegExp.$3, 10) == d.getFullYear() );
            }],
    ['validate-currency-dollar', 'Please enter a valid $ amount. For example $100.00 .', function(v) {
                // [$]1[##][,###]+[.##]
                // [$]1###+[.##]
                // [$]0.##
                // [$].##
                return Validator.get('IsEmpty').test(v) ||  /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)
            }],
    ['validate-selection', 'Please make a selection', function(v,elm){
                return elm.options ? elm.selectedIndex > 0 : !Validation.get('IsEmpty').test(v);
            }],
    ['validate-one-required', 'Please select one of the above options.', function (v,elm) {
                var p = elm.parentNode;
                var options = p.getElementsByTagName('INPUT');
                return $A(options).any(function(elm) {
                    return $F(elm);
                });
            }]
]); 
